/*BOXD为接线盒数字型，由宫老师开发。
BOXD和DT45数字型之间通过RS485相连，协议为modbus-rtu，BOXD为主机，提供各种寄存器。
RS485为DT45D的USART3。
*/
#include <stdio.h>
#include <string.h>

#include "stm32l4xx.h"
#include "stm32l4xx_ll_bus.h"
#include "stm32l4xx_ll_rcc.h"
#include "stm32l4xx_ll_gpio.h"
#include "stm32l4xx_ll_lpuart.h"
#include "stm32l4xx_ll_usart.h"


#include ".\bsp_dtu.h"






//const uint32_t _tbl_baud_dtu[]={/*1200,4800,*/9600,19200,38400,57600,115200, 0};
//const char* _tbl_fmt_ble[]={/*" 7-E-1", " 7-O-1",*/  FMT_8_n_2, FMT_8_O_1, FMT_8_E_1, FMT_8_n_1, NULL};




/*设置RS485的串口模式，波特率和当前状态。
*/
static void bsp_uart_dtu_config(const char* fmt, uint32_t baud, uint8_t sta)
{
	uint32_t pclk1_clock;
	uint32_t baud_rate;
	
	
	baud_rate= baud;

	if(baud_rate< 19200){	
		//使能HSI，并等待稳定。
		LL_RCC_HSI_Enable();
		while(0 == LL_RCC_HSI_IsReady()){}	//不能使用LL_RCC_IsActiveFlag_HSIRDY()。
			
		LL_RCC_SetUSARTClockSource(LL_RCC_USART3_CLKSOURCE_HSI);
	}
	else{
		LL_RCC_SetUSARTClockSource(LL_RCC_USART3_CLKSOURCE_SYSCLK);
	}
	
	pclk1_clock= LL_RCC_GetUSARTClockFreq(LL_RCC_USART3_CLKSOURCE);
	LL_USART_SetBaudRate(UART_DTU, pclk1_clock, 0, baud_rate);	//第3个参数是OverSampling。 QQ可以在USART使能时，更改波特率吗？

	

	LL_USART_Disable(UART_DTU);
		
	if(0){
	}
	else if(0 == strcmp(fmt, FMT_8_E_1)){
		LL_USART_ConfigCharacter(UART_DTU, LL_USART_DATAWIDTH_9B, LL_USART_PARITY_EVEN, LL_USART_STOPBITS_1);	//奇偶校验时，数据宽度须为9B。
	}
	else if(0 == strcmp(fmt, FMT_8_O_1)){
		LL_USART_ConfigCharacter(UART_DTU, LL_USART_DATAWIDTH_9B, LL_USART_PARITY_EVEN, LL_USART_STOPBITS_1);	//奇偶校验时，数据宽度须为9B。
	}
	else if(0 == strcmp(fmt, FMT_8_n_1)){
		LL_USART_ConfigCharacter(UART_DTU, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
	}
	else if(0 == strcmp(fmt, FMT_8_n_2)){
		LL_USART_ConfigCharacter(UART_DTU, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_2);
	}
	else{	//FMT_8_L_1...
		LL_USART_ConfigCharacter(UART_DTU, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
	}
	
	

	LL_USART_Enable(UART_DTU);
	

	
//	//根据波特率，设定接收超时时间（暂统一）
//	modbus_recv_info_dtu.tmo_max= 100;	//500ms
}



/*USART3的硬件：
PC4: USART3_TX
PC5: USART3_RX

*/
static void bsp_uart_dtu_hal(void)
{
	LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);

	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_4, LL_GPIO_MODE_ALTERNATE);
	LL_GPIO_SetAFPin_0_7(GPIOC, LL_GPIO_PIN_4, LL_GPIO_AF_7);				//C AF7 as USART3_TX.
	
	LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_5, LL_GPIO_PULL_UP);
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_5, LL_GPIO_MODE_ALTERNATE);
	LL_GPIO_SetAFPin_0_7(GPIOC, LL_GPIO_PIN_5, LL_GPIO_AF_7);				//C AF7 as USART3_RX.
}



/*配置MCU和BOXD盒相连的串口。
!!需要开启相应时钟。
!!115200用11520标示。
*/
void bsp_uart_dtu_init(uint32_t baud, const char* fmt)
{
	bsp_uart_dtu_hal();
	
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3);
	//LL_RCC_SetUSARTClockSource(LL_RCC_USART3_CLKSOURCE_SYSCLK);		//PCLK as USART1's clock source,!!Must enable USART1_EN@RCC_APB1ENR1.
	
	LL_USART_Disable(UART_DTU);	//因为会动态修改该串口参数，所以假定它处于使能状态，需先禁止。
	
	
	/*配置串口：中断接收，查询发送。
	帧格式：
	0：无校验：2位停止位
	1：奇校验，1位停止位；
	2：偶校验，1位停止位；
	3：无校验，1位停止位；
	波特率：
	0  9600");
	1  19200");
	2  38400");
	3  57600");
	4  115200");
	*/
//	uart_to_dtu_cfg.baud= baud;
//	strcpy(uart_to_dtu_cfg.fmt, fmt);
//	uart_to_dtu_cfg.sta= 0;
	
	//C OVER8@CR1=0, 16 samples.
	/* baudrate= fck/(8*(2-OVER8)*UARTDIV). UARTDIV= man.fra.
	例fpclk=84MHz，16samples，115200时，man.fra=45.5625，即0x2D9。
	具体参考RM0090's P978。
	*/
	bsp_uart_dtu_config(fmt, baud, 0);	//9600/19200/38400/57600

	
	LL_USART_EnableDirectionTx(UART_DTU);
	LL_USART_EnableDirectionRx(UART_DTU);
	LL_USART_Enable(UART_DTU);
	
	//LL_USART_EnableIT_RXNE(UART_DTU);
	
	
	/* preemption = 1, sub-priority = 1 */
	NVIC_SetPriority(UART_DTU_IRQn, 1);
	/* Enable Interrupt for UART channel */
	NVIC_EnableIRQ(UART_DTU_IRQn);
}

/************************ END OF FILE ************************/






